{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# \u7b2c\u5341\u4e09\u7ae0\uff1a\u811a\u672c\u7f16\u7a0b\u4e0e\u7cfb\u7edf\u7ba1\u7406\n \u8bb8\u591a\u4eba\u4f7f\u7528Python\u4f5c\u4e3a\u4e00\u4e2ashell\u811a\u672c\u7684\u66ff\u4ee3\uff0c\u7528\u6765\u5b9e\u73b0\u5e38\u7528\u7cfb\u7edf\u4efb\u52a1\u7684\u81ea\u52a8\u5316\uff0c\u5982\u6587\u4ef6\u7684\u64cd\u4f5c\uff0c\u7cfb\u7edf\u7684\u914d\u7f6e\u7b49\u3002\u672c\u7ae0\u7684\u4e3b\u8981\u76ee\u6807\u662f\u63cf\u8ff0\u5173\u4e8e\u7f16\u5199\u811a\u672c\u65f6\u5019\u7ecf\u5e38\u9047\u5230\u7684\u4e00\u4e9b\u529f\u80fd\u3002\u4f8b\u5982\uff0c\u89e3\u6790\u547d\u4ee4\u884c\u9009\u9879\u3001\u83b7\u53d6\u6709\u7528\u7684\u7cfb\u7edf\u914d\u7f6e\u6570\u636e\u7b49\u7b49\u3002\u7b2c5\u7ae0\u4e5f\u5305\u542b\u4e86\u4e0e\u6587\u4ef6\u548c\u76ee\u5f55\u76f8\u5173\u7684\u4e00\u822c\u4fe1\u606f\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 13.1 \u901a\u8fc7\u91cd\u5b9a\u5411/\u7ba1\u9053/\u6587\u4ef6\u63a5\u53d7\u8f93\u5165\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u5e0c\u671b\u4f60\u7684\u811a\u672c\u63a5\u53d7\u4efb\u4f55\u7528\u6237\u8ba4\u4e3a\u6700\u7b80\u5355\u7684\u8f93\u5165\u65b9\u5f0f\u3002\u5305\u62ec\u5c06\u547d\u4ee4\u884c\u7684\u8f93\u51fa\u901a\u8fc7\u7ba1\u9053\u4f20\u9012\u7ed9\u8be5\u811a\u672c\u3001\n\u91cd\u5b9a\u5411\u6587\u4ef6\u5230\u8be5\u811a\u672c\uff0c\u6216\u5728\u547d\u4ee4\u884c\u4e2d\u4f20\u9012\u4e00\u4e2a\u6587\u4ef6\u540d\u6216\u6587\u4ef6\u540d\u5217\u8868\u7ed9\u8be5\u811a\u672c\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Python\u5185\u7f6e\u7684 fileinput \u6a21\u5757\u8ba9\u8fd9\u4e2a\u53d8\u5f97\u7b80\u5355\u3002\u5982\u679c\u4f60\u6709\u4e00\u4e2a\u4e0b\u9762\u8fd9\u6837\u7684\u811a\u672c\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "#!/usr/bin/env python3\nimport fileinput\n\nwith fileinput.input() as f_input:\n    for line in f_input:\n        print(line, end='')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u90a3\u4e48\u4f60\u5c31\u80fd\u4ee5\u524d\u9762\u63d0\u5230\u7684\u6240\u6709\u65b9\u5f0f\u6765\u4e3a\u6b64\u811a\u672c\u63d0\u4f9b\u8f93\u5165\u3002\u5047\u8bbe\u4f60\u5c06\u6b64\u811a\u672c\u4fdd\u5b58\u4e3a filein.py \u5e76\u5c06\u5176\u53d8\u4e3a\u53ef\u6267\u884c\u6587\u4ef6\uff0c\n\u90a3\u4e48\u4f60\u53ef\u4ee5\u50cf\u4e0b\u9762\u8fd9\u6837\u8c03\u7528\u5b83\uff0c\u5f97\u5230\u671f\u671b\u7684\u8f93\u51fa\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "$ ls | ./filein.py          # Prints a directory listing to stdout.\n$ ./filein.py /etc/passwd   # Reads /etc/passwd to stdout.\n$ ./filein.py < /etc/passwd # Reads /etc/passwd to stdout."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "fileinput.input() \u521b\u5efa\u5e76\u8fd4\u56de\u4e00\u4e2a FileInput \u7c7b\u7684\u5b9e\u4f8b\u3002\n\u8be5\u5b9e\u4f8b\u9664\u4e86\u62e5\u6709\u4e00\u4e9b\u6709\u7528\u7684\u5e2e\u52a9\u65b9\u6cd5\u5916\uff0c\u5b83\u8fd8\u53ef\u88ab\u5f53\u505a\u4e00\u4e2a\u4e0a\u4e0b\u6587\u7ba1\u7406\u5668\u4f7f\u7528\u3002\n\u56e0\u6b64\uff0c\u6574\u5408\u8d77\u6765\uff0c\u5982\u679c\u6211\u4eec\u8981\u5199\u4e00\u4e2a\u6253\u5370\u591a\u4e2a\u6587\u4ef6\u8f93\u51fa\u7684\u811a\u672c\uff0c\u90a3\u4e48\u6211\u4eec\u9700\u8981\u5728\u8f93\u51fa\u4e2d\u5305\u542b\u6587\u4ef6\u540d\u548c\u884c\u53f7\uff0c\u5982\u4e0b\u6240\u793a\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import fileinput\nwith fileinput.input('/etc/passwd') as f:\n    for line in f:\n        print(f.filename(), f.lineno(), line, end='')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u901a\u8fc7\u5c06\u5b83\u4f5c\u4e3a\u4e00\u4e2a\u4e0a\u4e0b\u6587\u7ba1\u7406\u5668\u4f7f\u7528\uff0c\u53ef\u4ee5\u786e\u4fdd\u5b83\u4e0d\u518d\u4f7f\u7528\u65f6\u6587\u4ef6\u80fd\u81ea\u52a8\u5173\u95ed\uff0c\n\u800c\u4e14\u6211\u4eec\u5728\u4e4b\u540e\u8fd8\u6f14\u793a\u4e86 FileInput \u7684\u4e00\u4e9b\u6709\u7528\u7684\u5e2e\u52a9\u65b9\u6cd5\u6765\u83b7\u53d6\u8f93\u51fa\u4e2d\u7684\u4e00\u4e9b\u5176\u4ed6\u4fe1\u606f\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 13.2 \u7ec8\u6b62\u7a0b\u5e8f\u5e76\u7ed9\u51fa\u9519\u8bef\u4fe1\u606f\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u60f3\u5411\u6807\u51c6\u9519\u8bef\u6253\u5370\u4e00\u6761\u6d88\u606f\u5e76\u8fd4\u56de\u67d0\u4e2a\u975e\u96f6\u72b6\u6001\u7801\u6765\u7ec8\u6b62\u7a0b\u5e8f\u8fd0\u884c"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u6709\u4e00\u4e2a\u7a0b\u5e8f\u50cf\u4e0b\u9762\u8fd9\u6837\u7ec8\u6b62\uff0c\u629b\u51fa\u4e00\u4e2a SystemExit \u5f02\u5e38\uff0c\u4f7f\u7528\u9519\u8bef\u6d88\u606f\u4f5c\u4e3a\u53c2\u6570\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "raise SystemExit('It failed!')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5b83\u4f1a\u5c06\u6d88\u606f\u5728 sys.stderr \u4e2d\u6253\u5370\uff0c\u7136\u540e\u7a0b\u5e8f\u4ee5\u72b6\u6001\u78011\u9000\u51fa\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u672c\u8282\u867d\u7136\u5f88\u77ed\u5c0f\uff0c\u4f46\u662f\u5b83\u80fd\u89e3\u51b3\u5728\u5199\u811a\u672c\u65f6\u7684\u4e00\u4e2a\u5e38\u89c1\u95ee\u9898\u3002\n\u4e5f\u5c31\u662f\u8bf4\uff0c\u5f53\u4f60\u60f3\u8981\u7ec8\u6b62\u67d0\u4e2a\u7a0b\u5e8f\u65f6\uff0c\u4f60\u53ef\u80fd\u4f1a\u50cf\u4e0b\u9762\u8fd9\u6837\u5199\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import sys\nsys.stderr.write('It failed!\\n')\nraise SystemExit(1)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u4f60\u76f4\u63a5\u5c06\u6d88\u606f\u4f5c\u4e3a\u53c2\u6570\u4f20\u7ed9 SystemExit() \uff0c\u90a3\u4e48\u4f60\u53ef\u4ee5\u7701\u7565\u5176\u4ed6\u6b65\u9aa4\uff0c\n\u6bd4\u5982import\u8bed\u53e5\u6216\u5c06\u9519\u8bef\u6d88\u606f\u5199\u5165 sys.stderr"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 13.3 \u89e3\u6790\u547d\u4ee4\u884c\u9009\u9879\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u7684\u7a0b\u5e8f\u5982\u4f55\u80fd\u591f\u89e3\u6790\u547d\u4ee4\u884c\u9009\u9879\uff08\u4f4d\u4e8esys.argv\u4e2d\uff09"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "argparse \u6a21\u5757\u53ef\u88ab\u7528\u6765\u89e3\u6790\u547d\u4ee4\u884c\u9009\u9879\u3002\u4e0b\u9762\u4e00\u4e2a\u7b80\u5355\u4f8b\u5b50\u6f14\u793a\u4e86\u6700\u57fa\u672c\u7684\u7528\u6cd5\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# search.py\n'''\nHypothetical command-line tool for searching a collection of\nfiles for one or more text patterns.\n'''\nimport argparse\nparser = argparse.ArgumentParser(description='Search some files')\n\nparser.add_argument(dest='filenames',metavar='filename', nargs='*')\n\nparser.add_argument('-p', '--pat',metavar='pattern', required=True,\n                    dest='patterns', action='append',\n                    help='text pattern to search for')\n\nparser.add_argument('-v', dest='verbose', action='store_true',\n                    help='verbose mode')\n\nparser.add_argument('-o', dest='outfile', action='store',\n                    help='output file')\n\nparser.add_argument('--speed', dest='speed', action='store',\n                    choices={'slow','fast'}, default='slow',\n                    help='search speed')\n\nargs = parser.parse_args()\n\n# Output the collected arguments\nprint(args.filenames)\nprint(args.patterns)\nprint(args.verbose)\nprint(args.outfile)\nprint(args.speed)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8be5\u7a0b\u5e8f\u5b9a\u4e49\u4e86\u4e00\u4e2a\u5982\u4e0b\u4f7f\u7528\u7684\u547d\u4ee4\u884c\u89e3\u6790\u5668\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "bash % python3 search.py -h\nusage: search.py [-h] [-p pattern] [-v] [-o OUTFILE] [--speed {slow,fast}]\n                 [filename [filename ...]]\n\nSearch some files\n\npositional arguments:\n  filename\n\noptional arguments:\n  -h, --help            show this help message and exit\n  -p pattern, --pat pattern\n                        text pattern to search for\n  -v                    verbose mode\n  -o OUTFILE            output file\n  --speed {slow,fast}   search speed"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e0b\u9762\u7684\u90e8\u5206\u6f14\u793a\u4e86\u7a0b\u5e8f\u4e2d\u7684\u6570\u636e\u90e8\u5206\u3002\u4ed4\u7ec6\u89c2\u5bdfprint()\u8bed\u53e5\u7684\u6253\u5370\u8f93\u51fa\u3002"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "bash % python3 search.py foo.txt bar.txt\nusage: search.py [-h] -p pattern [-v] [-o OUTFILE] [--speed {fast,slow}]\n                 [filename [filename ...]]\nsearch.py: error: the following arguments are required: -p/--pat\n\nbash % python3 search.py -v -p spam --pat=eggs foo.txt bar.txt\nfilenames = ['foo.txt', 'bar.txt']\npatterns  = ['spam', 'eggs']\nverbose   = True\noutfile   = None\nspeed     = slow\n\nbash % python3 search.py -v -p spam --pat=eggs foo.txt bar.txt -o results\nfilenames = ['foo.txt', 'bar.txt']\npatterns  = ['spam', 'eggs']\nverbose   = True\noutfile   = results\nspeed     = slow\n\nbash % python3 search.py -v -p spam --pat=eggs foo.txt bar.txt -o results \\\n             --speed=fast\nfilenames = ['foo.txt', 'bar.txt']\npatterns  = ['spam', 'eggs']\nverbose   = True\noutfile   = results\nspeed     = fast"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5bf9\u4e8e\u9009\u9879\u503c\u7684\u8fdb\u4e00\u6b65\u5904\u7406\u7531\u7a0b\u5e8f\u6765\u51b3\u5b9a\uff0c\u7528\u4f60\u81ea\u5df1\u7684\u903b\u8f91\u6765\u66ff\u4ee3 print() \u51fd\u6570\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "argparse \u6a21\u5757\u662f\u6807\u51c6\u5e93\u4e2d\u6700\u5927\u7684\u6a21\u5757\u4e4b\u4e00\uff0c\u62e5\u6709\u5927\u91cf\u7684\u914d\u7f6e\u9009\u9879\u3002\n\u672c\u8282\u53ea\u662f\u6f14\u793a\u4e86\u5176\u4e2d\u6700\u57fa\u7840\u7684\u4e00\u4e9b\u7279\u6027\uff0c\u5e2e\u52a9\u4f60\u5165\u95e8\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e3a\u4e86\u89e3\u6790\u547d\u4ee4\u884c\u9009\u9879\uff0c\u4f60\u9996\u5148\u8981\u521b\u5efa\u4e00\u4e2a ArgumentParser \u5b9e\u4f8b\uff0c\n\u5e76\u4f7f\u7528 add_argument() \u65b9\u6cd5\u58f0\u660e\u4f60\u60f3\u8981\u652f\u6301\u7684\u9009\u9879\u3002\n\u5728\u6bcf\u4e2a add_argument() \u8c03\u7528\u4e2d\uff0cdest \u53c2\u6570\u6307\u5b9a\u89e3\u6790\u7ed3\u679c\u88ab\u6307\u6d3e\u7ed9\u5c5e\u6027\u7684\u540d\u5b57\u3002\nmetavar \u53c2\u6570\u88ab\u7528\u6765\u751f\u6210\u5e2e\u52a9\u4fe1\u606f\u3002action \u53c2\u6570\u6307\u5b9a\u8ddf\u5c5e\u6027\u5bf9\u5e94\u7684\u5904\u7406\u903b\u8f91\uff0c\n\u901a\u5e38\u7684\u503c\u4e3a store ,\u88ab\u7528\u6765\u5b58\u50a8\u67d0\u4e2a\u503c\u6216\u5c06\u591a\u4e2a\u53c2\u6570\u503c\u6536\u96c6\u5230\u4e00\u4e2a\u5217\u8868\u4e2d\u3002\n\u4e0b\u9762\u7684\u53c2\u6570\u6536\u96c6\u6240\u6709\u5269\u4f59\u7684\u547d\u4ee4\u884c\u53c2\u6570\u5230\u4e00\u4e2a\u5217\u8868\u4e2d\u3002\u5728\u672c\u4f8b\u4e2d\u5b83\u88ab\u7528\u6765\u6784\u9020\u4e00\u4e2a\u6587\u4ef6\u540d\u5217\u8868\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "parser.add_argument(dest='filenames',metavar='filename', nargs='*')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e0b\u9762\u7684\u53c2\u6570\u6839\u636e\u53c2\u6570\u662f\u5426\u5b58\u5728\u6765\u8bbe\u7f6e\u4e00\u4e2a Boolean \u6807\u5fd7\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "parser.add_argument('-v', dest='verbose', action='store_true',\n                    help='verbose mode')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e0b\u9762\u7684\u53c2\u6570\u63a5\u53d7\u4e00\u4e2a\u5355\u72ec\u503c\u5e76\u5c06\u5176\u5b58\u50a8\u4e3a\u4e00\u4e2a\u5b57\u7b26\u4e32\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "parser.add_argument('-o', dest='outfile', action='store',\n                    help='output file')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e0b\u9762\u7684\u53c2\u6570\u8bf4\u660e\u5141\u8bb8\u67d0\u4e2a\u53c2\u6570\u91cd\u590d\u51fa\u73b0\u591a\u6b21\uff0c\u5e76\u5c06\u5b83\u4eec\u8ffd\u52a0\u5230\u4e00\u4e2a\u5217\u8868\u4e2d\u53bb\u3002\nrequired \u6807\u5fd7\u8868\u793a\u8be5\u53c2\u6570\u81f3\u5c11\u8981\u6709\u4e00\u4e2a\u3002-p \u548c --pat \u8868\u793a\u4e24\u4e2a\u53c2\u6570\u540d\u5f62\u5f0f\u90fd\u53ef\u4f7f\u7528\u3002"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "parser.add_argument('-p', '--pat',metavar='pattern', required=True,\n                    dest='patterns', action='append',\n                    help='text pattern to search for')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u6700\u540e\uff0c\u4e0b\u9762\u7684\u53c2\u6570\u8bf4\u660e\u63a5\u53d7\u4e00\u4e2a\u503c\uff0c\u4f46\u662f\u4f1a\u5c06\u5176\u548c\u53ef\u80fd\u7684\u9009\u62e9\u503c\u505a\u6bd4\u8f83\uff0c\u4ee5\u68c0\u6d4b\u5176\u5408\u6cd5\u6027\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "parser.add_argument('--speed', dest='speed', action='store',\n                    choices={'slow','fast'}, default='slow',\n                    help='search speed')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e00\u65e6\u53c2\u6570\u9009\u9879\u88ab\u6307\u5b9a\uff0c\u4f60\u5c31\u53ef\u4ee5\u6267\u884c parser.parse() \u65b9\u6cd5\u4e86\u3002\n\u5b83\u4f1a\u5904\u7406 sys.argv \u7684\u503c\u5e76\u8fd4\u56de\u4e00\u4e2a\u7ed3\u679c\u5b9e\u4f8b\u3002\n\u6bcf\u4e2a\u53c2\u6570\u503c\u4f1a\u88ab\u8bbe\u7f6e\u6210\u8be5\u5b9e\u4f8b\u4e2d add_argument() \u65b9\u6cd5\u7684 dest \u53c2\u6570\u6307\u5b9a\u7684\u5c5e\u6027\u503c\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd8\u5f88\u591a\u79cd\u5176\u4ed6\u65b9\u6cd5\u89e3\u6790\u547d\u4ee4\u884c\u9009\u9879\u3002\n\u4f8b\u5982\uff0c\u4f60\u53ef\u80fd\u4f1a\u624b\u52a8\u7684\u5904\u7406 sys.argv \u6216\u8005\u4f7f\u7528 getopt \u6a21\u5757\u3002\n\u4f46\u662f\uff0c\u5982\u679c\u4f60\u91c7\u7528\u672c\u8282\u7684\u65b9\u5f0f\uff0c\u5c06\u4f1a\u51cf\u5c11\u5f88\u591a\u5197\u4f59\u4ee3\u7801\uff0c\u5e95\u5c42\u7ec6\u8282 argparse \u6a21\u5757\u5df2\u7ecf\u5e2e\u4f60\u5904\u7406\u4e86\u3002\n\u4f60\u53ef\u80fd\u8fd8\u4f1a\u78b0\u5230\u4f7f\u7528 optparse \u5e93\u89e3\u6790\u9009\u9879\u7684\u4ee3\u7801\u3002\n\u5c3d\u7ba1 optparse \u548c argparse \u5f88\u50cf\uff0c\u4f46\u662f\u540e\u8005\u66f4\u5148\u8fdb\uff0c\u56e0\u6b64\u5728\u65b0\u7684\u7a0b\u5e8f\u4e2d\u4f60\u5e94\u8be5\u4f7f\u7528\u5b83\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 13.4 \u8fd0\u884c\u65f6\u5f39\u51fa\u5bc6\u7801\u8f93\u5165\u63d0\u793a\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u5199\u4e86\u4e2a\u811a\u672c\uff0c\u8fd0\u884c\u65f6\u9700\u8981\u4e00\u4e2a\u5bc6\u7801\u3002\u6b64\u811a\u672c\u662f\u4ea4\u4e92\u5f0f\u7684\uff0c\u56e0\u6b64\u4e0d\u80fd\u5c06\u5bc6\u7801\u5728\u811a\u672c\u4e2d\u786c\u7f16\u7801\uff0c\n\u800c\u662f\u9700\u8981\u5f39\u51fa\u4e00\u4e2a\u5bc6\u7801\u8f93\u5165\u63d0\u793a\uff0c\u8ba9\u7528\u6237\u81ea\u5df1\u8f93\u5165\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u65f6\u5019Python\u7684 getpass \u6a21\u5757\u6b63\u662f\u4f60\u6240\u9700\u8981\u7684\u3002\u4f60\u53ef\u4ee5\u8ba9\u4f60\u5f88\u8f7b\u677e\u7684\u5f39\u51fa\u5bc6\u7801\u8f93\u5165\u63d0\u793a\uff0c\n\u5e76\u4e14\u4e0d\u4f1a\u5728\u7528\u6237\u7ec8\u7aef\u56de\u663e\u5bc6\u7801\u3002\u4e0b\u9762\u662f\u5177\u4f53\u4ee3\u7801\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import getpass\n\nuser = getpass.getuser()\npasswd = getpass.getpass()\n\nif svc_login(user, passwd):    # You must write svc_login()\n   print('Yay!')\nelse:\n   print('Boo!')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728\u6b64\u4ee3\u7801\u4e2d\uff0csvc_login() \u662f\u4f60\u8981\u5b9e\u73b0\u7684\u5904\u7406\u5bc6\u7801\u7684\u51fd\u6570\uff0c\u5177\u4f53\u7684\u5904\u7406\u8fc7\u7a0b\u4f60\u81ea\u5df1\u51b3\u5b9a\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u6ce8\u610f\u5728\u524d\u9762\u4ee3\u7801\u4e2d getpass.getuser() \u4e0d\u4f1a\u5f39\u51fa\u7528\u6237\u540d\u7684\u8f93\u5165\u63d0\u793a\u3002\n\u5b83\u4f1a\u6839\u636e\u8be5\u7528\u6237\u7684shell\u73af\u5883\u6216\u8005\u4f1a\u4f9d\u636e\u672c\u5730\u7cfb\u7edf\u7684\u5bc6\u7801\u5e93\uff08\u652f\u6301 pwd \u6a21\u5757\u7684\u5e73\u53f0\uff09\u6765\u4f7f\u7528\u5f53\u524d\u7528\u6237\u7684\u767b\u5f55\u540d\uff0c"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u4f60\u60f3\u663e\u793a\u7684\u5f39\u51fa\u7528\u6237\u540d\u8f93\u5165\u63d0\u793a\uff0c\u4f7f\u7528\u5185\u7f6e\u7684 input \u51fd\u6570\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "user = input('Enter your username: ')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd8\u6709\u4e00\u70b9\u5f88\u91cd\u8981\uff0c\u6709\u4e9b\u7cfb\u7edf\u53ef\u80fd\u4e0d\u652f\u6301 getpass() \u65b9\u6cd5\u9690\u85cf\u8f93\u5165\u5bc6\u7801\u3002\n\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0cPython\u4f1a\u63d0\u524d\u8b66\u544a\u4f60\u8fd9\u4e9b\u95ee\u9898\uff08\u4f8b\u5982\u5b83\u4f1a\u8b66\u544a\u4f60\u8bf4\u5bc6\u7801\u4f1a\u4ee5\u660e\u6587\u5f62\u5f0f\u663e\u793a\uff09"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 13.5 \u83b7\u53d6\u7ec8\u7aef\u7684\u5927\u5c0f\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u9700\u8981\u77e5\u9053\u5f53\u524d\u7ec8\u7aef\u7684\u5927\u5c0f\u4ee5\u4fbf\u6b63\u786e\u7684\u683c\u5f0f\u5316\u8f93\u51fa\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f7f\u7528 os.get_terminal_size() \u51fd\u6570\u6765\u505a\u5230\u8fd9\u4e00\u70b9\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4ee3\u7801\u793a\u4f8b\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import os\nsz = os.get_terminal_size()\nsz"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "sz.columns"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "sz.lines"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u6709\u592a\u591a\u65b9\u5f0f\u6765\u5f97\u77e5\u7ec8\u7aef\u5927\u5c0f\u4e86\uff0c\u4ece\u8bfb\u53d6\u73af\u5883\u53d8\u91cf\u5230\u6267\u884c\u5e95\u5c42\u7684 ioctl() \u51fd\u6570\u7b49\u7b49\u3002\n\u4e0d\u8fc7\uff0c\u4e3a\u4ec0\u4e48\u8981\u53bb\u7814\u7a76\u8fd9\u4e9b\u590d\u6742\u7684\u529e\u6cd5\u800c\u4e0d\u662f\u4ec5\u4ec5\u8c03\u7528\u4e00\u4e2a\u7b80\u5355\u7684\u51fd\u6570\u5462\uff1f"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 13.6 \u6267\u884c\u5916\u90e8\u547d\u4ee4\u5e76\u83b7\u53d6\u5b83\u7684\u8f93\u51fa\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u60f3\u6267\u884c\u4e00\u4e2a\u5916\u90e8\u547d\u4ee4\u5e76\u4ee5Python\u5b57\u7b26\u4e32\u7684\u5f62\u5f0f\u83b7\u53d6\u6267\u884c\u7ed3\u679c\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f7f\u7528 subprocess.check_output() \u51fd\u6570\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import subprocess\nout_bytes = subprocess.check_output(['netstat','-a'])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u6bb5\u4ee3\u7801\u6267\u884c\u4e00\u4e2a\u6307\u5b9a\u7684\u547d\u4ee4\u5e76\u5c06\u6267\u884c\u7ed3\u679c\u4ee5\u4e00\u4e2a\u5b57\u8282\u5b57\u7b26\u4e32\u7684\u5f62\u5f0f\u8fd4\u56de\u3002\n\u5982\u679c\u4f60\u9700\u8981\u6587\u672c\u5f62\u5f0f\u8fd4\u56de\uff0c\u52a0\u4e00\u4e2a\u89e3\u7801\u6b65\u9aa4\u5373\u53ef\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "out_text = out_bytes.decode('utf-8')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u88ab\u6267\u884c\u7684\u547d\u4ee4\u4ee5\u975e\u96f6\u7801\u8fd4\u56de\uff0c\u5c31\u4f1a\u629b\u51fa\u5f02\u5e38\u3002\n\u4e0b\u9762\u7684\u4f8b\u5b50\u6355\u83b7\u5230\u9519\u8bef\u5e76\u83b7\u53d6\u8fd4\u56de\u7801\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "try:\n    out_bytes = subprocess.check_output(['cmd','arg1','arg2'])\nexcept subprocess.CalledProcessError as e:\n    out_bytes = e.output       # Output generated before error\n    code      = e.returncode   # Return code"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0ccheck_output() \u4ec5\u4ec5\u8fd4\u56de\u8f93\u5165\u5230\u6807\u51c6\u8f93\u51fa\u7684\u503c\u3002\n\u5982\u679c\u4f60\u9700\u8981\u540c\u65f6\u6536\u96c6\u6807\u51c6\u8f93\u51fa\u548c\u9519\u8bef\u8f93\u51fa\uff0c\u4f7f\u7528 stderr \u53c2\u6570\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "out_bytes = subprocess.check_output(['cmd','arg1','arg2'],\n                                    stderr=subprocess.STDOUT)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u4f60\u9700\u8981\u7528\u4e00\u4e2a\u8d85\u65f6\u673a\u5236\u6765\u6267\u884c\u547d\u4ee4\uff0c\u4f7f\u7528 timeout \u53c2\u6570\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "try:\n    out_bytes = subprocess.check_output(['cmd','arg1','arg2'], timeout=5)\nexcept subprocess.TimeoutExpired as e:\n    ..."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u901a\u5e38\u6765\u8bb2\uff0c\u547d\u4ee4\u7684\u6267\u884c\u4e0d\u9700\u8981\u4f7f\u7528\u5230\u5e95\u5c42shell\u73af\u5883\uff08\u6bd4\u5982sh\u3001bash\uff09\u3002\n\u4e00\u4e2a\u5b57\u7b26\u4e32\u5217\u8868\u4f1a\u88ab\u4f20\u9012\u7ed9\u4e00\u4e2a\u4f4e\u7ea7\u7cfb\u7edf\u547d\u4ee4\uff0c\u6bd4\u5982 os.execve() \u3002\n\u5982\u679c\u4f60\u60f3\u8ba9\u547d\u4ee4\u88ab\u4e00\u4e2ashell\u6267\u884c\uff0c\u4f20\u9012\u4e00\u4e2a\u5b57\u7b26\u4e32\u53c2\u6570\uff0c\u5e76\u8bbe\u7f6e\u53c2\u6570 shell=True .\n\u6709\u65f6\u5019\u4f60\u60f3\u8981Python\u53bb\u6267\u884c\u4e00\u4e2a\u590d\u6742\u7684shell\u547d\u4ee4\u7684\u65f6\u5019\u8fd9\u4e2a\u5c31\u5f88\u6709\u7528\u4e86\uff0c\u6bd4\u5982\u7ba1\u9053\u6d41\u3001I/O\u91cd\u5b9a\u5411\u548c\u5176\u4ed6\u7279\u6027\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "out_bytes = subprocess.check_output('grep python | wc > out', shell=True)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u9700\u8981\u6ce8\u610f\u7684\u662f\u5728shell\u4e2d\u6267\u884c\u547d\u4ee4\u4f1a\u5b58\u5728\u4e00\u5b9a\u7684\u5b89\u5168\u98ce\u9669\uff0c\u7279\u522b\u662f\u5f53\u53c2\u6570\u6765\u81ea\u4e8e\u7528\u6237\u8f93\u5165\u65f6\u3002\n\u8fd9\u65f6\u5019\u53ef\u4ee5\u4f7f\u7528 shlex.quote() \u51fd\u6570\u6765\u5c06\u53c2\u6570\u6b63\u786e\u7684\u7528\u53cc\u5f15\u7528\u5f15\u8d77\u6765\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f7f\u7528 check_output() \u51fd\u6570\u662f\u6267\u884c\u5916\u90e8\u547d\u4ee4\u5e76\u83b7\u53d6\u5176\u8fd4\u56de\u503c\u7684\u6700\u7b80\u5355\u65b9\u5f0f\u3002\n\u4f46\u662f\uff0c\u5982\u679c\u4f60\u9700\u8981\u5bf9\u5b50\u8fdb\u7a0b\u505a\u66f4\u590d\u6742\u7684\u4ea4\u4e92\uff0c\u6bd4\u5982\u7ed9\u5b83\u53d1\u9001\u8f93\u5165\uff0c\u4f60\u5f97\u91c7\u7528\u53e6\u5916\u4e00\u79cd\u65b9\u6cd5\u3002\n\u8fd9\u65f6\u5019\u53ef\u76f4\u63a5\u4f7f\u7528 subprocess.Popen \u7c7b\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import subprocess\n\n# Some text to send\ntext = b'''\nhello world\nthis is a test\ngoodbye\n'''\n\n# Launch a command with pipes\np = subprocess.Popen(['wc'],\n          stdout = subprocess.PIPE,\n          stdin = subprocess.PIPE)\n\n# Send the data and get the output\nstdout, stderr = p.communicate(text)\n\n# To interpret as text, decode\nout = stdout.decode('utf-8')\nerr = stderr.decode('utf-8')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "subprocess \u6a21\u5757\u5bf9\u4e8e\u4f9d\u8d56TTY\u7684\u5916\u90e8\u547d\u4ee4\u4e0d\u5408\u9002\u7528\u3002\n\u4f8b\u5982\uff0c\u4f60\u4e0d\u80fd\u4f7f\u7528\u5b83\u6765\u81ea\u52a8\u5316\u4e00\u4e2a\u7528\u6237\u8f93\u5165\u5bc6\u7801\u7684\u4efb\u52a1\uff08\u6bd4\u5982\u4e00\u4e2assh\u4f1a\u8bdd\uff09\u3002\n\u8fd9\u65f6\u5019\uff0c\u4f60\u9700\u8981\u4f7f\u7528\u5230\u7b2c\u4e09\u65b9\u6a21\u5757\u4e86\uff0c\u6bd4\u5982\u57fa\u4e8e\u8457\u540d\u7684 expect \u5bb6\u65cf\u7684\u5de5\u5177\uff08pexpect\u6216\u7c7b\u4f3c\u7684\uff09"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 13.7 \u590d\u5236\u6216\u8005\u79fb\u52a8\u6587\u4ef6\u548c\u76ee\u5f55\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u60f3\u8981\u590d\u5236\u6216\u79fb\u52a8\u6587\u4ef6\u548c\u76ee\u5f55\uff0c\u4f46\u662f\u53c8\u4e0d\u60f3\u8c03\u7528shell\u547d\u4ee4\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "shutil \u6a21\u5757\u6709\u5f88\u591a\u4fbf\u6377\u7684\u51fd\u6570\u53ef\u4ee5\u590d\u5236\u6587\u4ef6\u548c\u76ee\u5f55\u3002\u4f7f\u7528\u8d77\u6765\u975e\u5e38\u7b80\u5355\uff0c\u6bd4\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import shutil\n\n# Copy src to dst. (cp src dst)\nshutil.copy(src, dst)\n\n# Copy files, but preserve metadata (cp -p src dst)\nshutil.copy2(src, dst)\n\n# Copy directory tree (cp -R src dst)\nshutil.copytree(src, dst)\n\n# Move src to dst (mv src dst)\nshutil.move(src, dst)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u4e9b\u51fd\u6570\u7684\u53c2\u6570\u90fd\u662f\u5b57\u7b26\u4e32\u5f62\u5f0f\u7684\u6587\u4ef6\u6216\u76ee\u5f55\u540d\u3002\n\u5e95\u5c42\u8bed\u4e49\u6a21\u62df\u4e86\u7c7b\u4f3c\u7684Unix\u547d\u4ee4\uff0c\u5982\u4e0a\u9762\u7684\u6ce8\u91ca\u90e8\u5206\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u5bf9\u4e8e\u7b26\u53f7\u94fe\u63a5\u800c\u5df2\u8fd9\u4e9b\u547d\u4ee4\u5904\u7406\u7684\u662f\u5b83\u6307\u5411\u7684\u4e1c\u897f\u3002\n\u4f8b\u5982\uff0c\u5982\u679c\u6e90\u6587\u4ef6\u662f\u4e00\u4e2a\u7b26\u53f7\u94fe\u63a5\uff0c\u90a3\u4e48\u76ee\u6807\u6587\u4ef6\u5c06\u4f1a\u662f\u7b26\u53f7\u94fe\u63a5\u6307\u5411\u7684\u6587\u4ef6\u3002\n\u5982\u679c\u4f60\u53ea\u60f3\u590d\u5236\u7b26\u53f7\u94fe\u63a5\u672c\u8eab\uff0c\u90a3\u4e48\u9700\u8981\u6307\u5b9a\u5173\u952e\u5b57\u53c2\u6570 follow_symlinks ,\u5982\u4e0b\uff1a"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u4f60\u60f3\u4fdd\u7559\u88ab\u590d\u5236\u76ee\u5f55\u4e2d\u7684\u7b26\u53f7\u94fe\u63a5\uff0c\u50cf\u8fd9\u6837\u505a\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "shutil.copytree(src, dst, symlinks=True)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "copytree() \u53ef\u4ee5\u8ba9\u4f60\u5728\u590d\u5236\u8fc7\u7a0b\u4e2d\u9009\u62e9\u6027\u7684\u5ffd\u7565\u67d0\u4e9b\u6587\u4ef6\u6216\u76ee\u5f55\u3002\n\u4f60\u53ef\u4ee5\u63d0\u4f9b\u4e00\u4e2a\u5ffd\u7565\u51fd\u6570\uff0c\u63a5\u53d7\u4e00\u4e2a\u76ee\u5f55\u540d\u548c\u6587\u4ef6\u540d\u5217\u8868\u4f5c\u4e3a\u8f93\u5165\uff0c\u8fd4\u56de\u4e00\u4e2a\u5ffd\u7565\u7684\u540d\u79f0\u5217\u8868\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "def ignore_pyc_files(dirname, filenames):\n    return [name in filenames if name.endswith('.pyc')]\n\nshutil.copytree(src, dst, ignore=ignore_pyc_files)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u7531\u4e8e\u5ffd\u7565\u67d0\u79cd\u6a21\u5f0f\u7684\u6587\u4ef6\u540d\u662f\u5f88\u5e38\u89c1\u7684\uff0c\u56e0\u6b64\u4e00\u4e2a\u4fbf\u6377\u7684\u51fd\u6570 ignore_patterns() \u5df2\u7ecf\u5305\u542b\u5728\u91cc\u9762\u4e86\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "shutil.copytree(src, dst, ignore=shutil.ignore_patterns('*~', '*.pyc'))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f7f\u7528 shutil \u590d\u5236\u6587\u4ef6\u548c\u76ee\u5f55\u4e5f\u5fd2\u7b80\u5355\u4e86\u70b9\u5427\u3002\n\u4e0d\u8fc7\uff0c\u5bf9\u4e8e\u6587\u4ef6\u5143\u6570\u636e\u4fe1\u606f\uff0ccopy2() \u8fd9\u6837\u7684\u51fd\u6570\u53ea\u80fd\u5c3d\u81ea\u5df1\u6700\u5927\u80fd\u529b\u6765\u4fdd\u7559\u5b83\u3002\n\u8bbf\u95ee\u65f6\u95f4\u3001\u521b\u5efa\u65f6\u95f4\u548c\u6743\u9650\u8fd9\u4e9b\u57fa\u672c\u4fe1\u606f\u4f1a\u88ab\u4fdd\u7559\uff0c\n\u4f46\u662f\u5bf9\u4e8e\u6240\u6709\u8005\u3001ACLs\u3001\u8d44\u6e90fork\u548c\u5176\u4ed6\u66f4\u6df1\u5c42\u6b21\u7684\u6587\u4ef6\u5143\u4fe1\u606f\u5c31\u8bf4\u4e0d\u51c6\u4e86\uff0c\n\u8fd9\u4e2a\u8fd8\u5f97\u4f9d\u8d56\u4e8e\u5e95\u5c42\u64cd\u4f5c\u7cfb\u7edf\u7c7b\u578b\u548c\u7528\u6237\u6240\u62e5\u6709\u7684\u8bbf\u95ee\u6743\u9650\u3002\n\u4f60\u901a\u5e38\u4e0d\u4f1a\u53bb\u4f7f\u7528 shutil.copytree() \u51fd\u6570\u6765\u6267\u884c\u7cfb\u7edf\u5907\u4efd\u3002\n\u5f53\u5904\u7406\u6587\u4ef6\u540d\u7684\u65f6\u5019\uff0c\u6700\u597d\u4f7f\u7528 os.path \u4e2d\u7684\u51fd\u6570\u6765\u786e\u4fdd\u6700\u5927\u7684\u53ef\u79fb\u690d\u6027\uff08\u7279\u522b\u662f\u540c\u65f6\u8981\u9002\u7528\u4e8eUnix\u548cWindows\uff09\u3002\n\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "filename = '/Users/guido/programs/spam.py'\nimport os.path\nos.path.basename(filename)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "os.path.dirname(filename)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "os.path.split(filename)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "os.path.join('/new/dir', os.path.basename(filename))"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "os.path.expanduser('~/guido/programs/spam.py')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f7f\u7528 copytree() \u590d\u5236\u6587\u4ef6\u5939\u7684\u4e00\u4e2a\u68d8\u624b\u7684\u95ee\u9898\u662f\u5bf9\u4e8e\u9519\u8bef\u7684\u5904\u7406\u3002\n\u4f8b\u5982\uff0c\u5728\u590d\u5236\u8fc7\u7a0b\u4e2d\uff0c\u51fd\u6570\u53ef\u80fd\u4f1a\u78b0\u5230\u635f\u574f\u7684\u7b26\u53f7\u94fe\u63a5\uff0c\u56e0\u4e3a\u6743\u9650\u65e0\u6cd5\u8bbf\u95ee\u6587\u4ef6\u7684\u95ee\u9898\u7b49\u7b49\u3002\n\u4e3a\u4e86\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\uff0c\u6240\u6709\u78b0\u5230\u7684\u95ee\u9898\u4f1a\u88ab\u6536\u96c6\u5230\u4e00\u4e2a\u5217\u8868\u4e2d\u5e76\u6253\u5305\u4e3a\u4e00\u4e2a\u5355\u72ec\u7684\u5f02\u5e38\uff0c\u5230\u4e86\u6700\u540e\u518d\u629b\u51fa\u3002\n\u4e0b\u9762\u662f\u4e00\u4e2a\u4f8b\u5b50\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "try:\n    shutil.copytree(src, dst)\nexcept shutil.Error as e:\n    for src, dst, msg in e.args[0]:\n         # src is source name\n         # dst is destination name\n         # msg is error message from exception\n         print(dst, src, msg)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u4f60\u63d0\u4f9b\u5173\u952e\u5b57\u53c2\u6570 ignore_dangling_symlinks=True \uff0c\n\u8fd9\u65f6\u5019 copytree() \u4f1a\u5ffd\u7565\u6389\u65e0\u6548\u7b26\u53f7\u94fe\u63a5\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u672c\u8282\u6f14\u793a\u7684\u8fd9\u4e9b\u51fd\u6570\u90fd\u662f\u6700\u5e38\u89c1\u7684\u3002\u4e0d\u8fc7\uff0cshutil \u8fd8\u6709\u66f4\u591a\u7684\u548c\u590d\u5236\u6570\u636e\u76f8\u5173\u7684\u64cd\u4f5c\u3002\n\u5b83\u7684\u6587\u6863\u5f88\u503c\u5f97\u4e00\u770b\uff0c\u53c2\u8003 Python documentation"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 13.8 \u521b\u5efa\u548c\u89e3\u538b\u5f52\u6863\u6587\u4ef6\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u9700\u8981\u521b\u5efa\u6216\u89e3\u538b\u5e38\u89c1\u683c\u5f0f\u7684\u5f52\u6863\u6587\u4ef6\uff08\u6bd4\u5982.tar, .tgz\u6216.zip\uff09"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "shutil \u6a21\u5757\u62e5\u6709\u4e24\u4e2a\u51fd\u6570\u2014\u2014 make_archive() \u548c unpack_archive() \u53ef\u6d3e\u4e0a\u7528\u573a\u3002\n\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import shutil\nshutil.unpack_archive('Python-3.3.0.tgz')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "shutil.make_archive('py33','zip','Python-3.3.0')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "make_archive() \u7684\u7b2c\u4e8c\u4e2a\u53c2\u6570\u662f\u671f\u671b\u7684\u8f93\u51fa\u683c\u5f0f\u3002\n\u53ef\u4ee5\u4f7f\u7528 get_archive_formats() \u83b7\u53d6\u6240\u6709\u652f\u6301\u7684\u5f52\u6863\u683c\u5f0f\u5217\u8868\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "shutil.get_archive_formats()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Python\u8fd8\u6709\u5176\u4ed6\u7684\u6a21\u5757\u53ef\u7528\u6765\u5904\u7406\u591a\u79cd\u5f52\u6863\u683c\u5f0f\uff08\u6bd4\u5982tarfile, zipfile, gzip, bz2\uff09\u7684\u5e95\u5c42\u7ec6\u8282\u3002\n\u4e0d\u8fc7\uff0c\u5982\u679c\u4f60\u4ec5\u4ec5\u53ea\u662f\u8981\u521b\u5efa\u6216\u63d0\u53d6\u67d0\u4e2a\u5f52\u6863\uff0c\u5c31\u6ca1\u6709\u5fc5\u8981\u4f7f\u7528\u5e95\u5c42\u5e93\u4e86\u3002\n\u53ef\u4ee5\u76f4\u63a5\u4f7f\u7528 shutil \u4e2d\u7684\u8fd9\u4e9b\u9ad8\u5c42\u51fd\u6570\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u4e9b\u51fd\u6570\u8fd8\u6709\u5f88\u591a\u5176\u4ed6\u9009\u9879\uff0c\u7528\u4e8e\u65e5\u5fd7\u6253\u5370\u3001\u9884\u68c0\u3001\u6587\u4ef6\u6743\u9650\u7b49\u7b49\u3002\n\u53c2\u8003 shutil\u6587\u6863"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 13.9 \u901a\u8fc7\u6587\u4ef6\u540d\u67e5\u627e\u6587\u4ef6\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u9700\u8981\u5199\u4e00\u4e2a\u6d89\u53ca\u5230\u6587\u4ef6\u67e5\u627e\u64cd\u4f5c\u7684\u811a\u672c\uff0c\u6bd4\u5982\u5bf9\u65e5\u5fd7\u5f52\u6863\u6587\u4ef6\u7684\u91cd\u547d\u540d\u5de5\u5177\uff0c\n\u4f60\u4e0d\u60f3\u5728Python\u811a\u672c\u4e2d\u8c03\u7528shell\uff0c\u6216\u8005\u4f60\u8981\u5b9e\u73b0\u4e00\u4e9bshell\u4e0d\u80fd\u505a\u7684\u529f\u80fd\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u67e5\u627e\u6587\u4ef6\uff0c\u53ef\u4f7f\u7528 os.walk() \u51fd\u6570\uff0c\u4f20\u4e00\u4e2a\u9876\u7ea7\u76ee\u5f55\u540d\u7ed9\u5b83\u3002\n\u4e0b\u9762\u662f\u4e00\u4e2a\u4f8b\u5b50\uff0c\u67e5\u627e\u7279\u5b9a\u7684\u6587\u4ef6\u540d\u5e76\u7b54\u5e94\u6240\u6709\u7b26\u5408\u6761\u4ef6\u7684\u6587\u4ef6\u5168\u8def\u5f84\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "#!/usr/bin/env python3.3\nimport os\n\ndef findfile(start, name):\n    for relpath, dirs, files in os.walk(start):\n        if name in files:\n            full_path = os.path.join(start, relpath, name)\n            print(os.path.normpath(os.path.abspath(full_path)))\n\nif __name__ == '__main__':\n    findfile(sys.argv[1], sys.argv[2])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4fdd\u5b58\u811a\u672c\u4e3a\u6587\u4ef6findfile.py\uff0c\u7136\u540e\u5728\u547d\u4ee4\u884c\u4e2d\u6267\u884c\u5b83\u3002\n\u6307\u5b9a\u521d\u59cb\u67e5\u627e\u76ee\u5f55\u4ee5\u53ca\u540d\u5b57\u4f5c\u4e3a\u4f4d\u7f6e\u53c2\u6570\uff0c\u5982\u4e0b\uff1a"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "os.walk() \u65b9\u6cd5\u4e3a\u6211\u4eec\u904d\u5386\u76ee\u5f55\u6811\uff0c\n\u6bcf\u6b21\u8fdb\u5165\u4e00\u4e2a\u76ee\u5f55\uff0c\u5b83\u4f1a\u8fd4\u56de\u4e00\u4e2a\u4e09\u5143\u7ec4\uff0c\u5305\u542b\u76f8\u5bf9\u4e8e\u67e5\u627e\u76ee\u5f55\u7684\u76f8\u5bf9\u8def\u5f84\uff0c\u4e00\u4e2a\u8be5\u76ee\u5f55\u4e0b\u7684\u76ee\u5f55\u540d\u5217\u8868\uff0c\n\u4ee5\u53ca\u90a3\u4e2a\u76ee\u5f55\u4e0b\u9762\u7684\u6587\u4ef6\u540d\u5217\u8868\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5bf9\u4e8e\u6bcf\u4e2a\u5143\u7ec4\uff0c\u53ea\u9700\u68c0\u6d4b\u4e00\u4e0b\u76ee\u6807\u6587\u4ef6\u540d\u662f\u5426\u5728\u6587\u4ef6\u5217\u8868\u4e2d\u3002\u5982\u679c\u662f\u5c31\u4f7f\u7528 os.path.join() \u5408\u5e76\u8def\u5f84\u3002\n\u4e3a\u4e86\u907f\u514d\u5947\u602a\u7684\u8def\u5f84\u540d\u6bd4\u5982 ././foo//bar \uff0c\u4f7f\u7528\u4e86\u53e6\u5916\u4e24\u4e2a\u51fd\u6570\u6765\u4fee\u6b63\u7ed3\u679c\u3002\n\u7b2c\u4e00\u4e2a\u662f os.path.abspath() ,\u5b83\u63a5\u53d7\u4e00\u4e2a\u8def\u5f84\uff0c\u53ef\u80fd\u662f\u76f8\u5bf9\u8def\u5f84\uff0c\u6700\u540e\u8fd4\u56de\u7edd\u5bf9\u8def\u5f84\u3002\n\u7b2c\u4e8c\u4e2a\u662f os.path.normpath() \uff0c\u7528\u6765\u8fd4\u56de\u6b63\u5e38\u8def\u5f84\uff0c\u53ef\u4ee5\u89e3\u51b3\u53cc\u659c\u6746\u3001\u5bf9\u76ee\u5f55\u7684\u591a\u91cd\u5f15\u7528\u7684\u95ee\u9898\u7b49\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5c3d\u7ba1\u8fd9\u4e2a\u811a\u672c\u76f8\u5bf9\u4e8eUNIX\u5e73\u53f0\u4e0a\u9762\u7684\u5f88\u591a\u67e5\u627e\u6765\u8bb2\u8981\u7b80\u5355\u5f88\u591a\uff0c\u5b83\u8fd8\u6709\u8de8\u5e73\u53f0\u7684\u4f18\u52bf\u3002\n\u5e76\u4e14\uff0c\u8fd8\u80fd\u5f88\u8f7b\u677e\u7684\u52a0\u5165\u5176\u4ed6\u7684\u529f\u80fd\u3002\n\u6211\u4eec\u518d\u6f14\u793a\u4e00\u4e2a\u4f8b\u5b50\uff0c\u4e0b\u9762\u7684\u51fd\u6570\u6253\u5370\u6240\u6709\u6700\u8fd1\u88ab\u4fee\u6539\u8fc7\u7684\u6587\u4ef6\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "#!/usr/bin/env python3.3\n\nimport os\nimport time\n\ndef modified_within(top, seconds):\n    now = time.time()\n    for path, dirs, files in os.walk(top):\n        for name in files:\n            fullpath = os.path.join(path, name)\n            if os.path.exists(fullpath):\n                mtime = os.path.getmtime(fullpath)\n                if mtime > (now - seconds):\n                    print(fullpath)\n\nif __name__ == '__main__':\n    import sys\n    if len(sys.argv) != 3:\n        print('Usage: {} dir seconds'.format(sys.argv[0]))\n        raise SystemExit(1)\n\n    modified_within(sys.argv[1], float(sys.argv[2]))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728\u6b64\u51fd\u6570\u7684\u57fa\u7840\u4e4b\u4e0a\uff0c\u4f7f\u7528os,os.path,glob\u7b49\u7c7b\u4f3c\u6a21\u5757\uff0c\u4f60\u5c31\u80fd\u5b9e\u73b0\u66f4\u52a0\u590d\u6742\u7684\u64cd\u4f5c\u4e86\u3002\n\u53ef\u53c2\u80035.11\u5c0f\u8282\u548c5.13\u5c0f\u8282\u7b49\u76f8\u5173\u7ae0\u8282\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 13.10 \u8bfb\u53d6\u914d\u7f6e\u6587\u4ef6\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u600e\u6837\u8bfb\u53d6\u666e\u901a.ini\u683c\u5f0f\u7684\u914d\u7f6e\u6587\u4ef6\uff1f"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "configparser \u6a21\u5757\u80fd\u88ab\u7528\u6765\u8bfb\u53d6\u914d\u7f6e\u6587\u4ef6\u3002\u4f8b\u5982\uff0c\u5047\u8bbe\u4f60\u6709\u5982\u4e0b\u7684\u914d\u7f6e\u6587\u4ef6\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "; config.ini\n; Sample configuration file\n\n[installation]\nlibrary=%(prefix)s/lib\ninclude=%(prefix)s/include\nbin=%(prefix)s/bin\nprefix=/usr/local\n\n# Setting related to debug configuration\n[debug]\nlog_errors=true\nshow_warnings=False\n\n[server]\nport: 8080\nnworkers: 32\npid-file=/tmp/spam.pid\nroot=/www/root\nsignature:\n    =================================\n    Brought to you by the Python Cookbook\n    ================================="
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e0b\u9762\u662f\u4e00\u4e2a\u8bfb\u53d6\u548c\u63d0\u53d6\u5176\u4e2d\u503c\u7684\u4f8b\u5b50\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "from configparser import ConfigParser\ncfg = ConfigParser()\ncfg.read('config.ini')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "cfg.sections()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "cfg.get('installation','library')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "cfg.getboolean('debug','log_errors')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "cfg.getint('server','port')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "cfg.getint('server','nworkers')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "print(cfg.get('server','signature'))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u6709\u9700\u8981\uff0c\u4f60\u8fd8\u80fd\u4fee\u6539\u914d\u7f6e\u5e76\u4f7f\u7528 cfg.write() \u65b9\u6cd5\u5c06\u5176\u5199\u56de\u5230\u6587\u4ef6\u4e2d\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "cfg.set('server','port','9000')\ncfg.set('debug','log_errors','False')\nimport sys\ncfg.write(sys.stdout)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u914d\u7f6e\u6587\u4ef6\u4f5c\u4e3a\u4e00\u79cd\u53ef\u8bfb\u6027\u5f88\u597d\u7684\u683c\u5f0f\uff0c\u975e\u5e38\u9002\u7528\u4e8e\u5b58\u50a8\u7a0b\u5e8f\u4e2d\u7684\u914d\u7f6e\u6570\u636e\u3002\n\u5728\u6bcf\u4e2a\u914d\u7f6e\u6587\u4ef6\u4e2d\uff0c\u914d\u7f6e\u6570\u636e\u4f1a\u88ab\u5206\u7ec4\uff08\u6bd4\u5982\u4f8b\u5b50\u4e2d\u7684\u201cinstallation\u201d\u3001 \u201cdebug\u201d \u548c \u201cserver\u201d\uff09\u3002\n\u6bcf\u4e2a\u5206\u7ec4\u5728\u5176\u4e2d\u6307\u5b9a\u5bf9\u5e94\u7684\u5404\u4e2a\u53d8\u91cf\u503c\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5bf9\u4e8e\u53ef\u5b9e\u73b0\u540c\u6837\u529f\u80fd\u7684\u914d\u7f6e\u6587\u4ef6\u548cPython\u6e90\u6587\u4ef6\u662f\u6709\u5f88\u5927\u7684\u4e0d\u540c\u7684\u3002\n\u9996\u5148\uff0c\u914d\u7f6e\u6587\u4ef6\u7684\u8bed\u6cd5\u8981\u66f4\u81ea\u7531\u4e9b\uff0c\u4e0b\u9762\u7684\u8d4b\u503c\u8bed\u53e5\u662f\u7b49\u6548\u7684\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "prefix=/usr/local\nprefix: /usr/local"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u914d\u7f6e\u6587\u4ef6\u4e2d\u7684\u540d\u5b57\u662f\u4e0d\u533a\u5206\u5927\u5c0f\u5199\u7684\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "cfg.get('installation','PREFIX')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "cfg.get('installation','prefix')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728\u89e3\u6790\u503c\u7684\u65f6\u5019\uff0cgetboolean() \u65b9\u6cd5\u67e5\u627e\u4efb\u4f55\u53ef\u884c\u7684\u503c\u3002\u4f8b\u5982\u4e0b\u9762\u90fd\u662f\u7b49\u4ef7\u7684\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "log_errors = true\nlog_errors = TRUE\nlog_errors = Yes\nlog_errors = 1"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u6216\u8bb8\u914d\u7f6e\u6587\u4ef6\u548cPython\u4ee3\u7801\u6700\u5927\u7684\u4e0d\u540c\u5728\u4e8e\uff0c\u5b83\u5e76\u4e0d\u662f\u4ece\u4e0a\u800c\u4e0b\u7684\u987a\u5e8f\u6267\u884c\u3002\n\u6587\u4ef6\u662f\u5b89\u88c5\u4e00\u4e2a\u6574\u4f53\u88ab\u8bfb\u53d6\u7684\u3002\u5982\u679c\u78b0\u5230\u4e86\u53d8\u91cf\u66ff\u6362\uff0c\u5b83\u5b9e\u9645\u4e0a\u5df2\u7ecf\u88ab\u66ff\u6362\u5b8c\u6210\u4e86\u3002\n\u4f8b\u5982\uff0c\u5728\u4e0b\u9762\u8fd9\u4e2a\u914d\u7f6e\u4e2d\uff0cprefix \u53d8\u91cf\u5728\u4f7f\u7528\u5b83\u7684\u53d8\u91cf\u4e4b\u524d\u6216\u4e4b\u540e\u5b9a\u4e49\u90fd\u662f\u53ef\u4ee5\u7684\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "[installation]\nlibrary=%(prefix)s/lib\ninclude=%(prefix)s/include\nbin=%(prefix)s/bin\nprefix=/usr/local"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "ConfigParser \u6709\u4e2a\u5bb9\u6613\u88ab\u5ffd\u89c6\u7684\u7279\u6027\u662f\u5b83\u80fd\u4e00\u6b21\u8bfb\u53d6\u591a\u4e2a\u914d\u7f6e\u6587\u4ef6\u7136\u540e\u5408\u5e76\u6210\u4e00\u4e2a\u914d\u7f6e\u3002\n\u4f8b\u5982\uff0c\u5047\u8bbe\u4e00\u4e2a\u7528\u6237\u50cf\u4e0b\u9762\u8fd9\u6837\u6784\u9020\u4e86\u4ed6\u4eec\u7684\u914d\u7f6e\u6587\u4ef6\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "; ~/.config.ini\n[installation]\nprefix=/Users/beazley/test\n\n[debug]\nlog_errors=False"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8bfb\u53d6\u8fd9\u4e2a\u6587\u4ef6\uff0c\u5b83\u5c31\u80fd\u8ddf\u4e4b\u524d\u7684\u914d\u7f6e\u5408\u5e76\u8d77\u6765\u3002\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# Previously read configuration\ncfg.get('installation', 'prefix')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# Merge in user-specific configuration\nimport os\ncfg.read(os.path.expanduser('~/.config.ini'))"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "cfg.get('installation', 'prefix')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "cfg.get('installation', 'library')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "cfg.getboolean('debug', 'log_errors')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4ed4\u7ec6\u89c2\u5bdf\u4e0b prefix \u53d8\u91cf\u662f\u600e\u6837\u8986\u76d6\u5176\u4ed6\u76f8\u5173\u53d8\u91cf\u7684\uff0c\u6bd4\u5982 library \u7684\u8bbe\u5b9a\u503c\u3002\n\u4ea7\u751f\u8fd9\u79cd\u7ed3\u679c\u7684\u539f\u56e0\u662f\u53d8\u91cf\u7684\u6539\u5199\u91c7\u53d6\u7684\u662f\u540e\u53d1\u5236\u4eba\u7b56\u7565\uff0c\u4ee5\u6700\u540e\u4e00\u4e2a\u4e3a\u51c6\u3002\n\u4f60\u53ef\u4ee5\u50cf\u4e0b\u9762\u8fd9\u6837\u505a\u8bd5\u9a8c\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "cfg.get('installation','library')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "cfg.set('installation','prefix','/tmp/dir')\ncfg.get('installation','library')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u6700\u540e\u8fd8\u6709\u5f88\u91cd\u8981\u4e00\u70b9\u8981\u6ce8\u610f\u7684\u662fPython\u5e76\u4e0d\u80fd\u652f\u6301.ini\u6587\u4ef6\u5728\u5176\u4ed6\u7a0b\u5e8f\uff08\u6bd4\u5982windows\u5e94\u7528\u7a0b\u5e8f\uff09\u4e2d\u7684\u6240\u6709\u7279\u6027\u3002\n\u786e\u4fdd\u4f60\u5df2\u7ecf\u53c2\u9605\u4e86configparser\u6587\u6863\u4e2d\u7684\u8bed\u6cd5\u8be6\u60c5\u4ee5\u53ca\u652f\u6301\u7279\u6027\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 13.11 \u7ed9\u7b80\u5355\u811a\u672c\u589e\u52a0\u65e5\u5fd7\u529f\u80fd\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u5e0c\u671b\u5728\u811a\u672c\u548c\u7a0b\u5e8f\u4e2d\u5c06\u8bca\u65ad\u4fe1\u606f\u5199\u5165\u65e5\u5fd7\u6587\u4ef6\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u6253\u5370\u65e5\u5fd7\u6700\u7b80\u5355\u65b9\u5f0f\u662f\u4f7f\u7528 logging \u6a21\u5757\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import logging\n\ndef main():\n    # Configure the logging system\n    logging.basicConfig(\n        filename='app.log',\n        level=logging.ERROR\n    )\n\n    # Variables (to make the calls that follow work)\n    hostname = 'www.python.org'\n    item = 'spam'\n    filename = 'data.csv'\n    mode = 'r'\n\n    # Example logging calls (insert into your program)\n    logging.critical('Host %s unknown', hostname)\n    logging.error(\"Couldn't find %r\", item)\n    logging.warning('Feature is deprecated')\n    logging.info('Opening file %r, mode=%r', filename, mode)\n    logging.debug('Got here')\n\nif __name__ == '__main__':\n    main()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e0a\u9762\u4e94\u4e2a\u65e5\u5fd7\u8c03\u7528\uff08critical(), error(), warning(), info(), debug()\uff09\u4ee5\u964d\u5e8f\u65b9\u5f0f\u8868\u793a\u4e0d\u540c\u7684\u4e25\u91cd\u7ea7\u522b\u3002\nbasicConfig() \u7684 level \u53c2\u6570\u662f\u4e00\u4e2a\u8fc7\u6ee4\u5668\u3002\n\u6240\u6709\u7ea7\u522b\u4f4e\u4e8e\u6b64\u7ea7\u522b\u7684\u65e5\u5fd7\u6d88\u606f\u90fd\u4f1a\u88ab\u5ffd\u7565\u6389\u3002\n\u6bcf\u4e2alogging\u64cd\u4f5c\u7684\u53c2\u6570\u662f\u4e00\u4e2a\u6d88\u606f\u5b57\u7b26\u4e32\uff0c\u540e\u9762\u518d\u8ddf\u4e00\u4e2a\u6216\u591a\u4e2a\u53c2\u6570\u3002\n\u6784\u9020\u6700\u7ec8\u7684\u65e5\u5fd7\u6d88\u606f\u7684\u65f6\u5019\u6211\u4eec\u4f7f\u7528\u4e86%\u64cd\u4f5c\u7b26\u6765\u683c\u5f0f\u5316\u6d88\u606f\u5b57\u7b26\u4e32\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd0\u884c\u8fd9\u4e2a\u7a0b\u5e8f\u540e\uff0c\u5728\u6587\u4ef6 app.log \u4e2d\u7684\u5185\u5bb9\u5e94\u8be5\u662f\u4e0b\u9762\u8fd9\u6837\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "CRITICAL:root:Host www.python.org unknown\nERROR:root:Could not find 'spam'"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u4f60\u60f3\u6539\u53d8\u8f93\u51fa\u7b49\u7ea7\uff0c\u4f60\u53ef\u4ee5\u4fee\u6539 basicConfig() \u8c03\u7528\u4e2d\u7684\u53c2\u6570\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "logging.basicConfig(\n     filename='app.log',\n     level=logging.WARNING,\n     format='%(levelname)s:%(asctime)s:%(message)s')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u6700\u540e\u8f93\u51fa\u53d8\u6210\u5982\u4e0b\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "CRITICAL:2012-11-20 12:27:13,595:Host www.python.org unknown\nERROR:2012-11-20 12:27:13,595:Could not find 'spam'\nWARNING:2012-11-20 12:27:13,595:Feature is deprecated"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e0a\u9762\u7684\u65e5\u5fd7\u914d\u7f6e\u90fd\u662f\u786c\u7f16\u7801\u5230\u7a0b\u5e8f\u4e2d\u7684\u3002\u5982\u679c\u4f60\u60f3\u4f7f\u7528\u914d\u7f6e\u6587\u4ef6\uff0c\n\u53ef\u4ee5\u50cf\u4e0b\u9762\u8fd9\u6837\u4fee\u6539 basicConfig() \u8c03\u7528\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import logging\nimport logging.config\n\ndef main():\n    # Configure the logging system\n    logging.config.fileConfig('logconfig.ini')\n    ..."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u521b\u5efa\u4e00\u4e2a\u4e0b\u9762\u8fd9\u6837\u7684\u6587\u4ef6\uff0c\u540d\u5b57\u53eb logconfig.ini \uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "[loggers]\nkeys=root\n\n[handlers]\nkeys=defaultHandler\n\n[formatters]\nkeys=defaultFormatter\n\n[logger_root]\nlevel=INFO\nhandlers=defaultHandler\nqualname=root\n\n[handler_defaultHandler]\nclass=FileHandler\nformatter=defaultFormatter\nargs=('app.log', 'a')\n\n[formatter_defaultFormatter]\nformat=%(levelname)s:%(name)s:%(message)s"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u4f60\u60f3\u4fee\u6539\u914d\u7f6e\uff0c\u53ef\u4ee5\u76f4\u63a5\u7f16\u8f91\u6587\u4ef6logconfig.ini\u5373\u53ef\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5c3d\u7ba1\u5bf9\u4e8e logging \u6a21\u5757\u800c\u5df2\u6709\u5f88\u591a\u66f4\u9ad8\u7ea7\u7684\u914d\u7f6e\u9009\u9879\uff0c\n\u4e0d\u8fc7\u8fd9\u91cc\u7684\u65b9\u6848\u5bf9\u4e8e\u7b80\u5355\u7684\u7a0b\u5e8f\u548c\u811a\u672c\u5df2\u7ecf\u8db3\u591f\u4e86\u3002\n\u53ea\u60f3\u5728\u8c03\u7528\u65e5\u5fd7\u64cd\u4f5c\u524d\u5148\u6267\u884c\u4e0bbasicConfig()\u51fd\u6570\u65b9\u6cd5\uff0c\u4f60\u7684\u7a0b\u5e8f\u5c31\u80fd\u4ea7\u751f\u65e5\u5fd7\u8f93\u51fa\u4e86\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u4f60\u60f3\u8981\u4f60\u7684\u65e5\u5fd7\u6d88\u606f\u5199\u5230\u6807\u51c6\u9519\u8bef\u4e2d\uff0c\u800c\u4e0d\u662f\u65e5\u5fd7\u6587\u4ef6\u4e2d\uff0c\u8c03\u7528 basicConfig() \u65f6\u4e0d\u4f20\u6587\u4ef6\u540d\u53c2\u6570\u5373\u53ef\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "logging.basicConfig(level=logging.INFO)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "basicConfig() \u5728\u7a0b\u5e8f\u4e2d\u53ea\u80fd\u88ab\u6267\u884c\u4e00\u6b21\u3002\u5982\u679c\u4f60\u7a0d\u540e\u60f3\u6539\u53d8\u65e5\u5fd7\u914d\u7f6e\uff0c\n\u5c31\u9700\u8981\u5148\u83b7\u53d6 root logger \uff0c\u7136\u540e\u76f4\u63a5\u4fee\u6539\u5b83\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "logging.getLogger().level = logging.DEBUG"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u9700\u8981\u5f3a\u8c03\u7684\u662f\u672c\u8282\u53ea\u662f\u6f14\u793a\u4e86 logging \u6a21\u5757\u7684\u4e00\u4e9b\u57fa\u672c\u7528\u6cd5\u3002\n\u5b83\u53ef\u4ee5\u505a\u66f4\u591a\u66f4\u9ad8\u7ea7\u7684\u5b9a\u5236\u3002\n\u5173\u4e8e\u65e5\u5fd7\u5b9a\u5236\u5316\u4e00\u4e2a\u5f88\u597d\u7684\u8d44\u6e90\u662f Logging Cookbook"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 13.12 \u7ed9\u51fd\u6570\u5e93\u589e\u52a0\u65e5\u5fd7\u529f\u80fd\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u60f3\u7ed9\u67d0\u4e2a\u51fd\u6570\u5e93\u589e\u52a0\u65e5\u5fd7\u529f\u80fd\uff0c\u4f46\u662f\u53c8\u4e0d\u80fd\u5f71\u54cd\u5230\u90a3\u4e9b\u4e0d\u4f7f\u7528\u65e5\u5fd7\u529f\u80fd\u7684\u7a0b\u5e8f\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5bf9\u4e8e\u60f3\u8981\u6267\u884c\u65e5\u5fd7\u64cd\u4f5c\u7684\u51fd\u6570\u5e93\u800c\u5df2\uff0c\u4f60\u5e94\u8be5\u521b\u5efa\u4e00\u4e2a\u4e13\u5c5e\u7684 logger \u5bf9\u8c61\uff0c\u5e76\u4e14\u50cf\u4e0b\u9762\u8fd9\u6837\u521d\u59cb\u5316\u914d\u7f6e\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# somelib.py\n\nimport logging\nlog = logging.getLogger(__name__)\nlog.addHandler(logging.NullHandler())\n\n# Example function (for testing)\ndef func():\n    log.critical('A Critical Error!')\n    log.debug('A debug message')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f7f\u7528\u8fd9\u4e2a\u914d\u7f6e\uff0c\u9ed8\u8ba4\u60c5\u51b5\u4e0b\u4e0d\u4f1a\u6253\u5370\u65e5\u5fd7\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import somelib\nsomelib.func()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e0d\u8fc7\uff0c\u5982\u679c\u914d\u7f6e\u8fc7\u65e5\u5fd7\u7cfb\u7edf\uff0c\u90a3\u4e48\u65e5\u5fd7\u6d88\u606f\u6253\u5370\u5c31\u5f00\u59cb\u751f\u6548\uff0c\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import logging\nlogging.basicConfig()\nsomelib.func()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u901a\u5e38\u6765\u8bb2\uff0c\u4f60\u4e0d\u5e94\u8be5\u5728\u51fd\u6570\u5e93\u4ee3\u7801\u4e2d\u81ea\u5df1\u914d\u7f6e\u65e5\u5fd7\u7cfb\u7edf\uff0c\u6216\u8005\u662f\u5df2\u7ecf\u5047\u5b9a\u6709\u4e2a\u5df2\u7ecf\u5b58\u5728\u7684\u65e5\u5fd7\u914d\u7f6e\u4e86\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8c03\u7528 getLogger(__name__) \u521b\u5efa\u4e00\u4e2a\u548c\u8c03\u7528\u6a21\u5757\u540c\u540d\u7684logger\u6a21\u5757\u3002\n\u7531\u4e8e\u6a21\u5757\u90fd\u662f\u552f\u4e00\u7684\uff0c\u56e0\u6b64\u521b\u5efa\u7684logger\u4e5f\u5c06\u662f\u552f\u4e00\u7684\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "log.addHandler(logging.NullHandler()) \u64cd\u4f5c\u5c06\u4e00\u4e2a\u7a7a\u5904\u7406\u5668\u7ed1\u5b9a\u5230\u521a\u521a\u5df2\u7ecf\u521b\u5efa\u597d\u7684logger\u5bf9\u8c61\u4e0a\u3002\n\u4e00\u4e2a\u7a7a\u5904\u7406\u5668\u9ed8\u8ba4\u4f1a\u5ffd\u7565\u8c03\u7528\u6240\u6709\u7684\u65e5\u5fd7\u6d88\u606f\u3002\n\u56e0\u6b64\uff0c\u5982\u679c\u4f7f\u7528\u8be5\u51fd\u6570\u5e93\u7684\u65f6\u5019\u8fd8\u6ca1\u6709\u914d\u7f6e\u65e5\u5fd7\uff0c\u90a3\u4e48\u5c06\u4e0d\u4f1a\u6709\u6d88\u606f\u6216\u8b66\u544a\u51fa\u73b0\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd8\u6709\u4e00\u70b9\u5c31\u662f\u5bf9\u4e8e\u5404\u4e2a\u51fd\u6570\u5e93\u7684\u65e5\u5fd7\u914d\u7f6e\u53ef\u4ee5\u662f\u76f8\u4e92\u72ec\u7acb\u7684\uff0c\u4e0d\u5f71\u54cd\u5176\u4ed6\u5e93\u7684\u65e5\u5fd7\u914d\u7f6e\u3002\n\u4f8b\u5982\uff0c\u5bf9\u4e8e\u5982\u4e0b\u7684\u4ee3\u7801\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import logging\nlogging.basicConfig(level=logging.ERROR)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import somelib\nsomelib.func()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# Change the logging level for 'somelib' only\nlogging.getLogger('somelib').level=logging.DEBUG\nsomelib.func()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728\u8fd9\u91cc\uff0c\u6839\u65e5\u5fd7\u88ab\u914d\u7f6e\u6210\u4ec5\u4ec5\u8f93\u51faERROR\u6216\u66f4\u9ad8\u7ea7\u522b\u7684\u6d88\u606f\u3002\n\u4e0d\u8fc7 \uff0csomelib \u7684\u65e5\u5fd7\u7ea7\u522b\u88ab\u5355\u72ec\u914d\u7f6e\u6210\u53ef\u4ee5\u8f93\u51fadebug\u7ea7\u522b\u7684\u6d88\u606f\uff0c\u5b83\u7684\u4f18\u5148\u7ea7\u6bd4\u5168\u5c40\u914d\u7f6e\u9ad8\u3002\n\u50cf\u8fd9\u6837\u66f4\u6539\u5355\u72ec\u6a21\u5757\u7684\u65e5\u5fd7\u914d\u7f6e\u5bf9\u4e8e\u8c03\u8bd5\u6765\u8bb2\u662f\u5f88\u65b9\u4fbf\u7684\uff0c\n\u56e0\u4e3a\u4f60\u65e0\u9700\u53bb\u66f4\u6539\u4efb\u4f55\u7684\u5168\u5c40\u65e5\u5fd7\u914d\u7f6e\u2014\u2014\u53ea\u9700\u8981\u4fee\u6539\u4f60\u60f3\u8981\u66f4\u591a\u8f93\u51fa\u7684\u6a21\u5757\u7684\u65e5\u5fd7\u7b49\u7ea7\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Logging HOWTO\n\u8be6\u7ec6\u4ecb\u7ecd\u4e86\u5982\u4f55\u914d\u7f6e\u65e5\u5fd7\u6a21\u5757\u548c\u5176\u4ed6\u6709\u7528\u6280\u5de7\uff0c\u53ef\u4ee5\u53c2\u9605\u4e0b\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 13.13 \u5b9e\u73b0\u4e00\u4e2a\u8ba1\u65f6\u5668\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u60f3\u8bb0\u5f55\u7a0b\u5e8f\u6267\u884c\u591a\u4e2a\u4efb\u52a1\u6240\u82b1\u8d39\u7684\u65f6\u95f4"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "time \u6a21\u5757\u5305\u542b\u5f88\u591a\u51fd\u6570\u6765\u6267\u884c\u8ddf\u65f6\u95f4\u6709\u5173\u7684\u51fd\u6570\u3002\n\u5c3d\u7ba1\u5982\u6b64\uff0c\u901a\u5e38\u6211\u4eec\u4f1a\u5728\u6b64\u57fa\u7840\u4e4b\u4e0a\u6784\u9020\u4e00\u4e2a\u66f4\u9ad8\u7ea7\u7684\u63a5\u53e3\u6765\u6a21\u62df\u4e00\u4e2a\u8ba1\u65f6\u5668\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import time\n\nclass Timer:\n    def __init__(self, func=time.perf_counter):\n        self.elapsed = 0.0\n        self._func = func\n        self._start = None\n\n    def start(self):\n        if self._start is not None:\n            raise RuntimeError('Already started')\n        self._start = self._func()\n\n    def stop(self):\n        if self._start is None:\n            raise RuntimeError('Not started')\n        end = self._func()\n        self.elapsed += end - self._start\n        self._start = None\n\n    def reset(self):\n        self.elapsed = 0.0\n\n    @property\n    def running(self):\n        return self._start is not None\n\n    def __enter__(self):\n        self.start()\n        return self\n\n    def __exit__(self, *args):\n        self.stop()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u4e2a\u7c7b\u5b9a\u4e49\u4e86\u4e00\u4e2a\u53ef\u4ee5\u88ab\u7528\u6237\u6839\u636e\u9700\u8981\u542f\u52a8\u3001\u505c\u6b62\u548c\u91cd\u7f6e\u7684\u8ba1\u65f6\u5668\u3002\n\u5b83\u4f1a\u5728 elapsed \u5c5e\u6027\u4e2d\u8bb0\u5f55\u6574\u4e2a\u6d88\u8017\u65f6\u95f4\u3002\n\u4e0b\u9762\u662f\u4e00\u4e2a\u4f8b\u5b50\u6765\u6f14\u793a\u600e\u6837\u4f7f\u7528\u5b83\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "def countdown(n):\n    while n > 0:\n        n -= 1\n\n# Use 1: Explicit start/stop\nt = Timer()\nt.start()\ncountdown(1000000)\nt.stop()\nprint(t.elapsed)\n\n# Use 2: As a context manager\nwith t:\n    countdown(1000000)\n\nprint(t.elapsed)\n\nwith Timer() as t2:\n    countdown(1000000)\nprint(t2.elapsed)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u672c\u8282\u63d0\u4f9b\u4e86\u4e00\u4e2a\u7b80\u5355\u800c\u5b9e\u7528\u7684\u7c7b\u6765\u5b9e\u73b0\u65f6\u95f4\u8bb0\u5f55\u4ee5\u53ca\u8017\u65f6\u8ba1\u7b97\u3002\n\u540c\u65f6\u4e5f\u662f\u5bf9\u4f7f\u7528with\u8bed\u53e5\u4ee5\u53ca\u4e0a\u4e0b\u6587\u7ba1\u7406\u5668\u534f\u8bae\u7684\u4e00\u4e2a\u5f88\u597d\u7684\u6f14\u793a\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728\u8ba1\u65f6\u4e2d\u8981\u8003\u8651\u4e00\u4e2a\u5e95\u5c42\u7684\u65f6\u95f4\u51fd\u6570\u95ee\u9898\u3002\u4e00\u822c\u6765\u8bf4\uff0c\n\u4f7f\u7528 time.time() \u6216 time.clock() \u8ba1\u7b97\u7684\u65f6\u95f4\u7cbe\u5ea6\u56e0\u64cd\u4f5c\u7cfb\u7edf\u7684\u4e0d\u540c\u4f1a\u6709\u6240\u4e0d\u540c\u3002\n\u800c\u4f7f\u7528 time.perf_counter() \u51fd\u6570\u53ef\u4ee5\u786e\u4fdd\u4f7f\u7528\u7cfb\u7edf\u4e0a\u9762\u6700\u7cbe\u786e\u7684\u8ba1\u65f6\u5668\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e0a\u8ff0\u4ee3\u7801\u4e2d\u7531 Timer \u7c7b\u8bb0\u5f55\u7684\u65f6\u95f4\u662f\u949f\u8868\u65f6\u95f4\uff0c\u5e76\u5305\u542b\u4e86\u6240\u6709\u4f11\u7720\u65f6\u95f4\u3002\n\u5982\u679c\u4f60\u53ea\u60f3\u8ba1\u7b97\u8be5\u8fdb\u7a0b\u6240\u82b1\u8d39\u7684CPU\u65f6\u95f4\uff0c\u5e94\u8be5\u4f7f\u7528 time.process_time() \u6765\u4ee3\u66ff\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "t = Timer(time.process_time)\nwith t:\n    countdown(1000000)\nprint(t.elapsed)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "time.perf_counter() \u548c time.process_time() \u90fd\u4f1a\u8fd4\u56de\u5c0f\u6570\u5f62\u5f0f\u7684\u79d2\u6570\u65f6\u95f4\u3002\n\u5b9e\u9645\u7684\u65f6\u95f4\u503c\u6ca1\u6709\u4efb\u4f55\u610f\u4e49\uff0c\u4e3a\u4e86\u5f97\u5230\u6709\u610f\u4e49\u7684\u7ed3\u679c\uff0c\u4f60\u5f97\u6267\u884c\u4e24\u6b21\u51fd\u6570\u7136\u540e\u8ba1\u7b97\u5b83\u4eec\u7684\u5dee\u503c\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u66f4\u591a\u5173\u4e8e\u8ba1\u65f6\u548c\u6027\u80fd\u5206\u6790\u7684\u4f8b\u5b50\u8bf7\u53c2\u800314.13\u5c0f\u8282\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 13.14 \u9650\u5236\u5185\u5b58\u548cCPU\u7684\u4f7f\u7528\u91cf\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u60f3\u5bf9\u5728Unix\u7cfb\u7edf\u4e0a\u9762\u8fd0\u884c\u7684\u7a0b\u5e8f\u8bbe\u7f6e\u5185\u5b58\u6216CPU\u7684\u4f7f\u7528\u9650\u5236\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "resource \u6a21\u5757\u80fd\u540c\u65f6\u6267\u884c\u8fd9\u4e24\u4e2a\u4efb\u52a1\u3002\u4f8b\u5982\uff0c\u8981\u9650\u5236CPU\u65f6\u95f4\uff0c\u53ef\u4ee5\u50cf\u4e0b\u9762\u8fd9\u6837\u505a\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import signal\nimport resource\nimport os\n\ndef time_exceeded(signo, frame):\n    print(\"Time's up!\")\n    raise SystemExit(1)\n\ndef set_max_runtime(seconds):\n    # Install the signal handler and set a resource limit\n    soft, hard = resource.getrlimit(resource.RLIMIT_CPU)\n    resource.setrlimit(resource.RLIMIT_CPU, (seconds, hard))\n    signal.signal(signal.SIGXCPU, time_exceeded)\n\nif __name__ == '__main__':\n    set_max_runtime(15)\n    while True:\n        pass"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u7a0b\u5e8f\u8fd0\u884c\u65f6\uff0cSIGXCPU \u4fe1\u53f7\u5728\u65f6\u95f4\u8fc7\u671f\u65f6\u88ab\u751f\u6210\uff0c\u7136\u540e\u6267\u884c\u6e05\u7406\u5e76\u9000\u51fa\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8981\u9650\u5236\u5185\u5b58\u4f7f\u7528\uff0c\u8bbe\u7f6e\u53ef\u4f7f\u7528\u7684\u603b\u5185\u5b58\u503c\u5373\u53ef\uff0c\u5982\u4e0b\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import resource\n\ndef limit_memory(maxsize):\n    soft, hard = resource.getrlimit(resource.RLIMIT_AS)\n    resource.setrlimit(resource.RLIMIT_AS, (maxsize, hard))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u50cf\u8fd9\u6837\u8bbe\u7f6e\u4e86\u5185\u5b58\u9650\u5236\u540e\uff0c\u7a0b\u5e8f\u8fd0\u884c\u5230\u6ca1\u6709\u591a\u4f59\u5185\u5b58\u65f6\u4f1a\u629b\u51fa MemoryError \u5f02\u5e38\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728\u672c\u8282\u4f8b\u5b50\u4e2d\uff0csetrlimit() \u51fd\u6570\u88ab\u7528\u6765\u8bbe\u7f6e\u7279\u5b9a\u8d44\u6e90\u4e0a\u9762\u7684\u8f6f\u9650\u5236\u548c\u786c\u9650\u5236\u3002\n\u8f6f\u9650\u5236\u662f\u4e00\u4e2a\u503c\uff0c\u5f53\u8d85\u8fc7\u8fd9\u4e2a\u503c\u7684\u65f6\u5019\u64cd\u4f5c\u7cfb\u7edf\u901a\u5e38\u4f1a\u53d1\u9001\u4e00\u4e2a\u4fe1\u53f7\u6765\u9650\u5236\u6216\u901a\u77e5\u8be5\u8fdb\u7a0b\u3002\n\u786c\u9650\u5236\u662f\u7528\u6765\u6307\u5b9a\u8f6f\u9650\u5236\u80fd\u8bbe\u5b9a\u7684\u6700\u5927\u503c\u3002\u901a\u5e38\u6765\u8bb2\uff0c\u8fd9\u4e2a\u7531\u7cfb\u7edf\u7ba1\u7406\u5458\u901a\u8fc7\u8bbe\u7f6e\u7cfb\u7edf\u7ea7\u53c2\u6570\u6765\u51b3\u5b9a\u3002\n\u5c3d\u7ba1\u786c\u9650\u5236\u53ef\u4ee5\u6539\u5c0f\u4e00\u70b9\uff0c\u4f46\u662f\u6700\u597d\u4e0d\u8981\u4f7f\u7528\u7528\u6237\u8fdb\u7a0b\u53bb\u4fee\u6539\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "setrlimit() \u51fd\u6570\u8fd8\u80fd\u88ab\u7528\u6765\u8bbe\u7f6e\u5b50\u8fdb\u7a0b\u6570\u91cf\u3001\u6253\u5f00\u6587\u4ef6\u6570\u4ee5\u53ca\u7c7b\u4f3c\u7cfb\u7edf\u8d44\u6e90\u7684\u9650\u5236\u3002\n\u66f4\u591a\u8be6\u60c5\u8bf7\u53c2\u8003 resource \u6a21\u5757\u7684\u6587\u6863\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u9700\u8981\u6ce8\u610f\u7684\u662f\u672c\u8282\u5185\u5bb9\u53ea\u80fd\u9002\u7528\u4e8eUnix\u7cfb\u7edf\uff0c\u5e76\u4e14\u4e0d\u4fdd\u8bc1\u6240\u6709\u7cfb\u7edf\u90fd\u80fd\u5982\u671f\u5de5\u4f5c\u3002\n\u6bd4\u5982\u6211\u4eec\u5728\u6d4b\u8bd5\u7684\u65f6\u5019\uff0c\u5b83\u80fd\u5728Linux\u4e0a\u9762\u6b63\u5e38\u8fd0\u884c\uff0c\u4f46\u662f\u5728OS X\u4e0a\u5374\u4e0d\u80fd\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 13.15 \u542f\u52a8\u4e00\u4e2aWEB\u6d4f\u89c8\u5668\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u60f3\u901a\u8fc7\u811a\u672c\u542f\u52a8\u6d4f\u89c8\u5668\u5e76\u6253\u5f00\u6307\u5b9a\u7684URL\u7f51\u9875"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "webbrowser \u6a21\u5757\u80fd\u88ab\u7528\u6765\u542f\u52a8\u4e00\u4e2a\u6d4f\u89c8\u5668\uff0c\u5e76\u4e14\u4e0e\u5e73\u53f0\u65e0\u5173\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import webbrowser\nwebbrowser.open('http://www.python.org')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5b83\u4f1a\u4f7f\u7528\u9ed8\u8ba4\u6d4f\u89c8\u5668\u6253\u5f00\u6307\u5b9a\u7f51\u9875\u3002\u5982\u679c\u4f60\u8fd8\u60f3\u5bf9\u7f51\u9875\u6253\u5f00\u65b9\u5f0f\u505a\u66f4\u591a\u63a7\u5236\uff0c\u8fd8\u53ef\u4ee5\u4f7f\u7528\u4e0b\u9762\u8fd9\u4e9b\u51fd\u6570\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# Open the page in a new browser window\nwebbrowser.open_new('http://www.python.org')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# Open the page in a new browser tab\nwebbrowser.open_new_tab('http://www.python.org')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u6837\u5c31\u53ef\u4ee5\u6253\u5f00\u4e00\u4e2a\u65b0\u7684\u6d4f\u89c8\u5668\u7a97\u53e3\u6216\u8005\u6807\u7b7e\uff0c\u53ea\u8981\u6d4f\u89c8\u5668\u652f\u6301\u5c31\u884c\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u4f60\u60f3\u6307\u5b9a\u6d4f\u89c8\u5668\u7c7b\u578b\uff0c\u53ef\u4ee5\u4f7f\u7528 webbrowser.get() \u51fd\u6570\u6765\u6307\u5b9a\u67d0\u4e2a\u7279\u5b9a\u6d4f\u89c8\u5668\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "c = webbrowser.get('firefox')\nc.open('http://www.python.org')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "c.open_new_tab('http://docs.python.org')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5bf9\u4e8e\u652f\u6301\u7684\u6d4f\u89c8\u5668\u540d\u79f0\u5217\u8868\u53ef\u67e5\u9605`Python\u6587\u6863 <http://docs.python.org/3/library/webbrowser.html>`_"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728\u811a\u672c\u4e2d\u6253\u5f00\u6d4f\u89c8\u5668\u6709\u65f6\u5019\u4f1a\u5f88\u6709\u7528\u3002\u4f8b\u5982\uff0c\u67d0\u4e2a\u811a\u672c\u6267\u884c\u67d0\u4e2a\u670d\u52a1\u5668\u53d1\u5e03\u4efb\u52a1\uff0c\n\u4f60\u60f3\u5feb\u901f\u6253\u5f00\u4e00\u4e2a\u6d4f\u89c8\u5668\u6765\u786e\u4fdd\u5b83\u5df2\u7ecf\u6b63\u5e38\u8fd0\u884c\u4e86\u3002\n\u6216\u8005\u662f\u67d0\u4e2a\u7a0b\u5e8f\u4ee5HTML\u7f51\u9875\u683c\u5f0f\u8f93\u51fa\u6570\u636e\uff0c\u4f60\u60f3\u6253\u5f00\u6d4f\u89c8\u5668\u67e5\u770b\u7ed3\u679c\u3002\n\u4e0d\u7ba1\u662f\u4e0a\u9762\u54ea\u79cd\u60c5\u51b5\uff0c\u4f7f\u7528 webbrowser \u6a21\u5757\u90fd\u662f\u4e00\u4e2a\u7b80\u5355\u5b9e\u7528\u7684\u89e3\u51b3\u65b9\u6848\u3002"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.7.1"
    },
    "toc": {
      "base_numbering": 1,
      "nav_menu": {},
      "number_sections": true,
      "sideBar": true,
      "skip_h1_title": true,
      "title_cell": "Table of Contents",
      "title_sidebar": "Contents",
      "toc_cell": false,
      "toc_position": {},
      "toc_section_display": true,
      "toc_window_display": true
    }
  },
  "nbformat": 4,
  "nbformat_minor": 2
}